/*
 * @Description: 大前端学习
 * @Version: H5
 * @Author: Ajax
 * @Date: 2020-05-11 10:01:11
 * @LastEditors: Ajax
 * @LastEditTime: 2020-05-11 18:56:41
 */



// --------------------------------Tools---------------------------------------------------------------
; (function () {
    let Tools = {
        getRandom: (min, max) => {
            return Math.floor(Math.random() * (max - min + 1) + min)
        }
    }
    window.Tools = Tools
})()

    // -------------------------------food--------------------------------------------------------------
    ; (function () {
        let position = 'absolute'

        // foods 用于存放创建的食物
        let foods = []

        function Food(options) {
            options = options || {}
            this.x = options.x || 0
            this.y = options.y || 0

            this.width = options.width || 20
            this.height = options.height || 20

            this.color = options.color || '#2ecd44'
        }

        // 渲染
        Food.prototype.render = function (map) {
            // 删除之前创建的食物
            remove()
            let foodBox = document.createElement('div')
            map.appendChild(foodBox)

            foods.push(foodBox)

            // 设置随机 x 和 y
            this.x = Tools.getRandom(0, map.offsetWidth / this.width - 1) * this.width
            this.y = Tools.getRandom(0, map.offsetHeight / this.height - 1) * this.height


            // 食物样式
            foodBox.style.position = position
            foodBox.style.left = this.x + 'px'
            foodBox.style.top = this.y + 'px'

            foodBox.style.width = this.width + 'px'
            foodBox.style.height = this.height + 'px'

            foodBox.style.backgroundColor = this.color
        }

        // 删除食物
        remove = () => {
            for (let i = foods.length - 1; i >= 0; i--) {
                //    删除foodBox
                foods[i].parentNode.removeChild(foods[i])
                //  删除数组中的元素
                foods.length--
            }
        }

        window.Food = Food
    })()

    // ------------------------------------snake--------------------------------------------------------
    ; (function () {
        let position = 'absolute'
        // 记录创建的蛇
        let snakes = []
        function Snake(options) {
            // 蛇节的大小
            options = options || {}
            this.width = options.width || 20
            this.height = options.height || 20

            // 蛇移动的方向
            this.direction = options.diretion || 'right'

            // 蛇的身体, 第一元素是蛇头部
            this.body = [
                { x: 3, y: 2, color: 'red' },
                { x: 2, y: 2, color: 'pink' },
                { x: 1, y: 2, color: 'hotpink' }
            ]
        }

        // 渲染蛇
        Snake.prototype.render = function (map) {
            // 删除之前创建的蛇
            remove()

            for (let i = 0, len = this.body.length; i < len; i++) {
                // 蛇节的身体属性
                let smallSnake = this.body[i]

                // 创建蛇节
                let snakeBox = document.createElement('div')

                // 添加蛇样式
                snakeBox.style.position = position
                snakeBox.style.top = smallSnake.y * this.width + 'px'
                snakeBox.style.left = smallSnake.x * this.height + 'px'
                snakeBox.style.width = this.width + 'px'
                snakeBox.style.height = this.height + 'px'
                snakeBox.style.backgroundColor = smallSnake.color

                map.appendChild(snakeBox)
                snakes.push(snakeBox)
            }
        }

        // 删除蛇节
        function remove() {
            for (let i = snakes.length - 1; i >= 0; i--) {
                // 删除蛇节
                snakes[i].parentNode.removeChild(snakes[i])
                // 删除数组中的元素
                snakes.length--
            }
        }

        // 控制蛇移动的方向和增加蛇节数
        Snake.prototype.move = function (food, map) {
            // 控制蛇的身体移动 (当前蛇节 到 上一个蛇节的位置)
            for (let i = this.body.length - 1; i > 0; i--) {
                this.body[i].x = this.body[i - 1].x
                this.body[i].y = this.body[i - 1].y
            }
            // 控制蛇头的移动
            // 判断蛇头移动的方向
            let snakeHead = this.body[0]
            switch (this.direction) {
                case 'right':
                    snakeHead.x++
                    break
                case 'left':
                    snakeHead.x--
                    break
                case 'top':
                    snakeHead.y--
                    break
                case 'bottom':
                    snakeHead.y++
                    break
            }
            // 蛇吃食物 (判断蛇头是否和食物的坐标重合)
            let headX = snakeHead.x * this.width
            let headY = snakeHead.y * this.height
            if (food.x === headX && food.y === headY) {
                // 让蛇增加一节
                let last = this.body[this.body.length - 1]
                this.body.push({
                    x: last.x,
                    y: last.y,
                    color: last.color
                })
                // 随机生成食物
                food.render(map)
            }
        }
        window.Snake = Snake
    })()

    // --------------------------------------------------game--------------------------------------------
    ; (function () {
        let that = null     // 改变 this 指向
        function Game(map) {
            this.food = new Food()
            this.snake = new Snake()
            this.map = map
            // 出作用域
            that = this
        }

        // 开始游戏
        Game.prototype.start = function () {
            // 渲染
            this.food.render(this.map)
            this.snake.render(this.map)

            // 测试 move方法
            // this.snake.move()
            // this.snake.render(this.map)

            // 游戏逻辑处理
            // 1 蛇自动移动
            autoMove()
            // 2 键盘控制蛇移动的方向
            controlSnake()
            // 3 蛇吃食物
        }

        // 控制蛇
        function controlSnake() {
            document.addEventListener('keydown', (e) => {
                switch (e.keyCode) {
                    case 37:
                        that.snake.direction = 'left'
                        break
                    case 38:
                        that.snake.direction = 'top'
                        break
                    case 39:
                        that.snake.direction = 'right'
                        break
                    case 40:
                        that.snake.direction = 'bottom'
                        break
                }
            }, false)
        }

        // 蛇自动移动
        function autoMove() {
            let time = setInterval(() => {   // this 指向 window
                // 让蛇走一格
                that.snake.move(that.food, that.map)
                that.snake.render(that.map)
                // 2 限定边界
                // 获取蛇的坐标
                let maxX = that.map.offsetWidth / that.snake.width
                let maxY = that.map.offsetHeight / that.snake.height
                let headX = that.snake.body[0].x
                let headY = that.snake.body[0].y
                if (headX < 0 || headX >= maxX) {
                    alert('Game over')
                    clearInterval(time)
                }
                if (headY < 0 || headY >= maxY) {
                    alert('Game over')
                    clearInterval(time)
                }
            }, 150);
            window.time = time
        }
        window.Game = Game
    })()

    // ---------------------------------------------游戏功能--------------------------------------------------
    ; (function () {
        let $beginBtn = document.querySelector('.begin')
        let $stop = $beginBtn.nextElementSibling
        let $map = document.querySelector('.map')
        $beginBtn.addEventListener('click', () => {
            let game = new Game($map)
            game.start()
        })
        $stop.addEventListener('click', () => {
            if (time) {
                clearInterval(time)
                $stop.innerHTML = '继续游戏'
            } else {
                // 空缺
                $stop.innerHTML = '暂停游戏'
            }
        })
    })()